﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using System.Web;
using System.Diagnostics;
using ModbusTestTool;
namespace Listener
{
    public class AjaxHandler
    {
        //internal map to the listner
        HttpListener m_listener;
        private volatile bool m_close = false;
        
        public delegate List<Registers> getDataDel();
        

        public delegate void UpdateHandlerDel(object sender, UpdateData e);
        
        /// <summary>
        /// WHen the class needs to update data it will fire off thise event
        /// </summary>
        public event UpdateHandlerDel onNeedUpdate;
        
        /// <summary>
        /// Set this delegate so the class can get xml data from another class
        /// </summary>
        public getDataDel getData;

        protected virtual void OnUpdate(UpdateData e)
        {
            if (onNeedUpdate != null)
            {
                // Invokes the delegates. 
                onNeedUpdate(this, e);
            }
        }




        public AjaxHandler(string[] prefixes)
        {
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            
            
            if (!HttpListener.IsSupported)
            {
                Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
                throw new Exception("Http listener is not supported"); ;
            }

            m_listener = new HttpListener();

            foreach (string s in prefixes)
            {
                m_listener.Prefixes.Add(s);
            }
        }

        public class UpdateData : EventArgs
        {
            public Registers data;

            public UpdateData(string command, int register, string value)
            {
                data = new Registers();
                data.name = command;
                data.number = register;
                data.value = value;
            }
        }

        
        

        public class Registers
        {
            public string name { set; get; }
            public int number { set; get; }
            public string value { set; get; }

            public Registers(string _name, int _number, string _value)
            {
                name = _name;
                number = _number;
                value = _value;
            }
            public Registers()
            {
                name = "None";
                number = 38000;
            }
        }

        public class commandObject
        {
            public string command;
            public List<string> arguments;
        }
       

        public void stop()
        {
            m_close = true;
            m_listener.Abort();
        }
        
        public  void Listen()
        {
            List<Registers> respose_example = new List<Registers>();
            
            int iter = 0;
            
            Registers test = new Registers();
            while (!m_close)
            {
                
                m_listener.Start();
                Debug.WriteLine("Listening..." + iter++.ToString());

               
           


                // Note: The GetContext method blocks while waiting for a request. 
                try
                {
                    HttpListenerContext context = m_listener.GetContext();

                    HttpListenerRequest request = context.Request;

                    // Obtain a response object.
                    HttpListenerResponse response = context.Response;


                    //sets up serializer for our list
                   
                    

                    StreamReader inHandle = new StreamReader(request.InputStream);
                    string inputString = inHandle.ReadToEnd();
                    if (inputString != string.Empty)
                    {
                        JavaScriptSerializer serial = new JavaScriptSerializer();
                        string unescapedstring = Regex.Unescape(HttpUtility.UrlDecode(inputString));
                        commandObject command = serial.Deserialize<commandObject>(unescapedstring);

                        if (command.command == "xml")
                        {
                            response.ContentType = "text/xml";
                            StringWriter stringToWrite = new StringWriter();

                            respose_example = getData();


                            System.Xml.Serialization.XmlSerializer outSeralizeList = new System.Xml.Serialization.XmlSerializer(typeof(List<Registers>));
                            outSeralizeList.Serialize(stringToWrite, respose_example);
                            string responseString = stringToWrite.ToString();

                            // Construct a response.

                            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                            // Get a response stream and write the response to it.
                            response.ContentLength64 = buffer.Length;
                            Stream output = response.OutputStream;
                            output.Write(buffer, 0, buffer.Length);

                            // You must close the output stream.
                            output.Close();
                        }else if(command.command == "login")
                        {
                            string user = command.arguments[0];
                            string pass = command.arguments[1];

                            if ((user == "sam") && (pass == "1234"))
                            {
                                string responseString = "cookie accepted";

                                // Construct a response.

                                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                                // Get a response stream and write the response to it.
                                response.ContentLength64 = buffer.Length;

                                Cookie cookie = new Cookie("user", "sam");

                                response.AppendCookie(cookie);
                                Stream output = response.OutputStream;
                                output.Write(buffer, 0, buffer.Length);
                                
                                // You must close the output stream.
                                output.Close();

                            }
                        }
                        else if (command.command == "quit")
                        {

                            m_close = true;
                            byte[] buffer = System.Text.Encoding.UTF8.GetBytes("OK");
                            // Get a response stream and write the response to it.
                            response.ContentLength64 = buffer.Length;
                            Stream output = response.OutputStream;
                            output.Write(buffer, 0, buffer.Length);
                            output.Close();
                        }
                        else if (command.command == "modify")
                        {
                            string[] response_args = command.arguments.ToArray();

                            if (response_args[1] != null)
                            {
                                //m_link_to_parent.update_value(int.Parse(response_args[0]), float.Parse(response_args[1]));
                                
                                response.ContentType = "text/htm";
                                string responseString = "ok";
                                UpdateData data = new UpdateData("update",int.Parse(response_args[0]),response_args[1]);
                                OnUpdate(data);
                                // Construct a response.
                                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                                // Get a response stream and write the response to it.
                                response.ContentLength64 = buffer.Length;
                                Stream output = response.OutputStream;
                                output.Write(buffer, 0, buffer.Length);
                                // You must close the output stream.
                                output.Close();
                            }
                        }

                    }
                    else
                    {
                        Serve_Page(response);
                    }

                    m_listener.Stop();
                }
                catch (Exception err )
                {
                    using (StreamWriter errLong = new StreamWriter("err.log", true))
                    {
                        errLong.WriteLine(err.Message);
                    }
                    goto quit;
                }
            }

        quit:

            return;


        }

        

        private  string Serve_Page(HttpListenerResponse response)
        {
            string html;
            using (StreamReader inHandle = new StreamReader("webInterface.html"))
            {
                html = inHandle.ReadToEnd();
            }

            byte[] buffer2 = System.Text.Encoding.UTF8.GetBytes(html);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer2.Length;
            System.IO.Stream output2 = response.OutputStream;
            output2.Write(buffer2, 0, buffer2.Length);
            output2.Close();
            return html;
        }
    }
}
